const targetMap = new WeakMap()

function track(target, key) {
    let depsMap = targetMap.get(target)
    if (!depsMap) {
        targetMap.set(target, (depsMap = new Map()))
    }

    let dep = depsMap.get(key)
    if (!dep) {
        depsMap.set(key, (dep = new Set()))
    }

    dep.add(effect)
}

function trigger(target, key) {
    const depsMap = targetMap.get(target)
    if (!depsMap) return

    const dep = depsMap.get(key)
    if (dep) {
        dep.forEach(effect => {
            effect()
        })
    }
}

const product = { price: 5, quantity: 2 }
let total = 0;

const effect = () => { total = product.price * product.quantity }

track(product, 'quantity');
effect()

console.log('total:', total)
product.quantity = 3
console.log('total:', total)
trigger(product, 'quantity')
console.log('total:', total)
